package com.smarthome.common.httpwapper;

import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 
 * 守护线程，释放过期连接
 * <p>
 * 经典阻塞I/O模型的一个主要缺点就是只有当阻塞I/O时，socket才能对I/O事件做出反应。 当连接被管理器收回后，这个连接仍然存活，但是却无法监控socket的状态，也无法对I/O事件做出反馈。 如果连接被服务器端关闭了，客户端监测不到连接的状态变化（也就无法根据连接状态的变化，关闭本地的socket）。
 * HttpClient为了缓解这一问题造成的影响，会在使用某个连接前，监测这个连接是否已经过时，如果服务器端关闭了连接， 那么连接就会失效。这种过时检查并不是100%有效，并且会给每个请求增加10到30毫秒额外开销。唯一一个可行的， 且does not involve a one thread per socket model for idle
 * connections的解决办法，是建立一个监控线程，来专门回收由于长时间不活动而被判定为失效的连接。 这个监控线程可以周期性的调用ClientConnectionManager类的closeExpiredConnections()方法来关闭过期的连接，
 * 回收连接池中被关闭的连接,也可以选择性的调用ClientConnectionManager类的closeIdleConnections()方法来关闭一段时间内不活动的连接。
 */
public class ExpiredConnMonitorThread extends Thread {

    private static final Logger LOGGER = LoggerFactory.getLogger(ExpiredConnMonitorThread.class);

    private final HttpClientConnectionPoolManager connMgr;

    private volatile boolean shutdown;

    public ExpiredConnMonitorThread(HttpClientConnectionPoolManager connMgr, boolean isDaemon) {
        super();
        this.setName("expired-connection-monitor");
        this.connMgr = connMgr;
        this.setDaemon(isDaemon);
    }

    @Override
    public void run() {
        try {
            while (!shutdown) {
                synchronized (this) {
                    wait(5 * 1000);
                    if (connMgr != null) {
                        // Close expired connections
                        if (LOGGER.isDebugEnabled()) {
                            // LOGGER.debug("关闭过期和超过空闲设定值的http请求连接...");
                        }
                        connMgr.closeExpiredConnections();
                        // Optionally, close connections
                        // that have been idle longer than 30 sec
                        connMgr.closeIdleConnections(30, TimeUnit.SECONDS);
                        if (LOGGER.isDebugEnabled()) {
                            // LOGGER.debug("关闭过期和超过空闲设定值的http请求连接完成");
                        }
                    }
                }
            }
        } catch (Exception ex) {
            shutdown();
        }
    }

    public void shutdown() {
        shutdown = true;
        synchronized (this) {
            notifyAll();
        }
    }
}
